package com.example.demo.aop;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.mapper.OperateLogMapper;
import com.example.demo.pojo.OperateLog;
import com.example.demo.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.stream.Collectors;

@Slf4j
@Aspect
@Component
public class LogAspect {

    @Autowired
    OperateLogMapper operateLogMapper;

    @Autowired
    HttpServletRequest httpServletRequest;//获取当前请求对象

    @Around("@annotation(com.example.demo.anno.Log)")
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        // 1. 使用Builder模式创建日志对象
        OperateLog.OperateLogBuilder logBuilder = OperateLog.builder()
                .operateTime(LocalDateTime.now())
                .className(joinPoint.getTarget().getClass().getName())
                .methodName(joinPoint.getSignature().getName());

        // 2. 增强异常处理
        try {
            String jwt = httpServletRequest.getHeader("token");
            Claims claims = JwtUtils.parseJWT(jwt);
            logBuilder.operateUser((Integer) claims.get("id"));
        } catch (Exception e) {
            log.error("解析JWT令牌失败: {}", e.getMessage());
            throw new RuntimeException("身份验证失败");
        }

        // 3. 参数处理（添加敏感信息过滤）
        Object[] args = joinPoint.getArgs();
        String methodParams = Arrays.stream(args)
                .map(arg -> {
                    String paramStr = arg.toString();
                    // 简单过滤密码字段（可根据需求扩展）
                    return paramStr.replaceAll("(?i)password=[^&]*", "password=***");
                })
                .collect(Collectors.joining(", ", "[", "]"));
        logBuilder.methodParams(methodParams);

        long begin = System.currentTimeMillis();
        try {
            Object result = joinPoint.proceed();
            long end = System.currentTimeMillis();
            
            // 4. 返回值处理（限制长度）
            String returnValue = JSONObject.toJSONString(result);
            if (returnValue.length() > 2000) {
                returnValue = returnValue.substring(0, 2000) + "...(truncated)";
            }
            logBuilder.returnValue(returnValue)
                     .costTime(end - begin);
            
            return result;
        } catch (Throwable t) {
            logBuilder.returnValue("方法执行异常: " + t.getMessage());
            throw t;
        } finally {
            // 5. 异步记录日志（需要配合异步配置）
            OperateLog finalLog = logBuilder.build();
            log.info("操作日志记录: {}", finalLog);
            operateLogMapper.insert(finalLog);
        }
    }
}
